package controller;

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 注解为websocket服务器，每个连接都创建一个对象
 *
 * @author zhangyanqi
 * @since 1.0 2017/11/30
 */

@ServerEndpoint(value = "/chattingRoom", subprotocols = {}, decoders = ChattingRoomDecoder.
        class, encoders = ChattingRoomEncoder.class, configurator = ChattingRoomConfig.class)
public class ChattingRoom {

    /**
     * 存储一共有多少个session
     */
    private static volatile Map<String, Session> sessions = new ConcurrentHashMap<String, Session>();

    /**
     * 记录多少人在线
     */
    private static volatile AtomicInteger totalPeople = new AtomicInteger(0);

    /**
     * 代表连接的session
     */
    private Session session;

    /**
     * session创建时
     *
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("session创建" + session.getId());
        sessions.put(session.getId(), session);
        while (true) {
            if (totalPeople.compareAndSet(totalPeople.get(), totalPeople.get() + 1)) {
                break;
            }
        }
        this.session = session;
        System.out.println("一共" + totalPeople.get() + "人");
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() throws IOException {
        sessions.remove(session.getId());
        session.close();
        while (true) {
            if (totalPeople.compareAndSet(totalPeople.get(), totalPeople.get() - 1)) {
                break;
            }
        }
    }

    /**
     * 当消息来的时候的方法
     *
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(Message message, Session session) throws IOException {
        if (!session.isOpen()) {
            onClose();
            return;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        String string = objectMapper.writeValueAsString(message);
        Set<Map.Entry<String, Session>> entries = sessions.entrySet();
        Iterator<Map.Entry<String, Session>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Session s = iterator.next().getValue();
            if (s.isOpen()) {
                RemoteEndpoint.Async asyncRemote = s.getAsyncRemote();
                asyncRemote.sendText(string);
            } else {
                s.close();
            }
        }
    }
}
